package studio.raptor.ddal.core.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import studio.raptor.ddal.core.connection.BackendDataSourceManager;
import studio.raptor.ddal.core.connection.jdbc.HikariDataSource;
import studio.raptor.ddal.core.connection.jdbc.HikariPoolMXBean;
import studio.raptor.ddal.core.log.bo.ConnPoolLogData;
import studio.raptor.ddal.core.log.common.CommonMethodUtil;
import studio.raptor.ddal.core.log.common.LogClientConstant;
import javax.sql.DataSource;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 异步批量处理日志
 */
public class AsyncMonitorProcessor{

	private static Logger logger = LoggerFactory.getLogger(AsyncMonitorProcessor.class);
	private static boolean runFlag = false;
	/**
	 * 用于执行ID申请的线程池
	 */
	public static ExecutorService monitorExecutor = Executors.newSingleThreadExecutor();

	public AsyncMonitorProcessor(){
		if("y".equalsIgnoreCase( LogClientConstant.monitorSwitch )){
			this.runFlag=true;
			monitorExecutor.submit( new MonitorWorker() );
		}
	}


	/**
	 * 获取数据库连接池信息,并存入本地队列
	 */
	private void getConnPoolLogData(){
//		logger.info("AsyncMonitorProcessor getConnPoolLogData 读取数据库连接池信息");
		Map<String, DataSource> dataSourceGroup = BackendDataSourceManager.instance().getPoolNameIndexedDataSources();
		if (null != dataSourceGroup && dataSourceGroup.size() > 0) {
			for (Map.Entry<String, DataSource> entry : dataSourceGroup.entrySet()) {
				HikariDataSource dataSource = (HikariDataSource) entry.getValue();
				ConnPoolLogData connPoolLogData=new ConnPoolLogData();
				connPoolLogData.setPoolName( dataSource.getPoolName() );
				connPoolLogData.setReadOnly( dataSource.isReadOnly() );
				connPoolLogData.setConnectionTimeout( dataSource.getConnectionTimeout() );
				connPoolLogData.setIdleTimeout( dataSource.getIdleTimeout() );
				connPoolLogData.setJdbcUrl( dataSource.getJdbcUrl() );
				connPoolLogData.setUsername( dataSource.getUsername());
				connPoolLogData.setMaxPoolSize( dataSource.getMaximumPoolSize() );
				connPoolLogData.setMinIdle( dataSource.getMinimumIdle() );
				HikariPoolMXBean mxb = ((HikariDataSource) entry.getValue()).getHikariPoolMXBean();
				connPoolLogData.setTotalConnections( mxb.getTotalConnections() );
				connPoolLogData.setActiveConnections( mxb.getActiveConnections() );
				connPoolLogData.setIdleConnections( mxb.getIdleConnections() );
				connPoolLogData.setAwaitingConnections( mxb.getThreadsAwaitingConnection() );
				connPoolLogData.setAcceptTime( new Date() );
				//放入本地队列
				LogClientUtil.process(connPoolLogData);
			}
		}
	}


	/**
	 * 采集监控信息并存入本地队列
	 */
	private class MonitorWorker implements Runnable {
		@Override
		public void run() {
			while(runFlag){
				try{
					//获取数据库连接池信息,并存入本地队列
					getConnPoolLogData();
				}catch(Exception e){
					logger.error("AsyncMonitorProcessor:MonitorWorker get monitor info error",e);
				}
				CommonMethodUtil.waitSleep( LogClientConstant.monitorTime);
			}
			if(!runFlag){
				//休息2分钟后再扫描
				CommonMethodUtil.waitSleep(120000);
			}
		}
	}


	public static void main(String[] args) {
		Map<String, DataSource> dataSourceGroup = BackendDataSourceManager.instance().getPoolNameIndexedDataSources();
		if (null != dataSourceGroup && dataSourceGroup.size() > 0) {
			for (Map.Entry<String, DataSource> entry : dataSourceGroup.entrySet()) {
				System.out.println( "AsyncMonitorProcessor  HikariDataSource " + entry.getKey() );
				HikariDataSource dataSource = (HikariDataSource) entry.getValue();
				System.out.println( dataSource.getPoolName() );
				System.out.println( dataSource.isReadOnly() );
				System.out.println( dataSource.isClosed() );
				System.out.println( dataSource.getConnectionTimeout() );
				System.out.println( dataSource.getIdleTimeout() );
				System.out.println( dataSource.getMaxLifetime() );
				System.out.println( dataSource.getMaximumPoolSize() );
				System.out.println( dataSource.getMinimumIdle() );
				System.out.println( dataSource.getJdbcUrl() );
				System.out.println( dataSource.getUsername() + "\n" );
				HikariPoolMXBean mxb = ((HikariDataSource) entry.getValue()).getHikariPoolMXBean();
				System.out.println( "AsyncMonitorProcessor  HikariPoolMXBean \n" );
				System.out.println( mxb.getTotalConnections() );
				System.out.println( mxb.getActiveConnections() );
				System.out.println( mxb.getIdleConnections() );
				System.out.println( mxb.getThreadsAwaitingConnection() + "\n" );
			}
		}
	}


}